package com.runa.monitor.platinterface.platService;

import com.runa.monitor.comm.entity.*;
import com.runa.monitor.comm.enums.NetEquTypeEnum;
import com.runa.monitor.comm.enums.RegionTypeEnum;
import com.runa.persistence.repository.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class RepositoryService implements CommandLineRunner {

    private CommNetEquipmentRepository commNetEquipmentRepository;
    private CommMeterRepository commMeterRepository;
    private CommValveRepository commValveRepository;
    private CommPanelRepository commPanelRepository;
    private CommTemperaturepressureRepository commTemperaturepressureRepository;
    private CommNbcmdRepository commNbcmdRepository;
    @Override
    public void run(String... args) throws Exception {
        Executors
                .newSingleThreadScheduledExecutor()
                .scheduleAtFixedRate(() -> commNetEquipmentRepository
                                .findAll()
                                .forEach(netEqu -> netEquipmentMap.put(netEqu.getSerial(), netEqu)),
                        0, 1, TimeUnit.MINUTES);
    }

    @Resource
    public void setCommNbcmdRepository(CommNbcmdRepository commNbcmdRepository) {
        this.commNbcmdRepository = commNbcmdRepository;
    }

    @Resource
    public void setCommValveRepository(CommValveRepository commValveRepository) {
        this.commValveRepository = commValveRepository;
    }

    @Resource
    public void setCommPanelRepository(CommPanelRepository commPanelRepository) {
        this.commPanelRepository = commPanelRepository;
    }

    @Resource
    public void setCommMeterRepository(CommMeterRepository commMeterRepository) {
        this.commMeterRepository = commMeterRepository;
    }

    @Resource
    public void setCommNetEquipmentRepository(CommNetEquipmentRepository commNetEquipmentRepository) {
        this.commNetEquipmentRepository = commNetEquipmentRepository;
    }

    @Resource
    public void setCommTemperaturepressureRepository(CommTemperaturepressureRepository commTemperaturepressureRepository) {
        this.commTemperaturepressureRepository = commTemperaturepressureRepository;
    }


    /**
     * 网络设备查找信息
     */
    public CommNetEquipment getCommNetEquipmentByIdentity(String identity) {
        Optional<CommNetEquipment> commNetEquipment = commNetEquipmentRepository.findById(identity);
        return commNetEquipment.orElse(null);
    }


    public CommNetEquipment getCommNetEquipmentByModelAndSerial(String model, String serial) {
        return commNetEquipmentRepository.findByModelAndSerial(model, serial);
    }

//    LoadingCache<String, Optional<CommNetEquipment>> cneCache = CacheBuilder
//            .newBuilder()
//            .expireAfterWrite(3600, TimeUnit.SECONDS)
//            .recordStats()
//            .build(new CacheLoader<String, Optional<CommNetEquipment>>() {
//                @Override
//                public Optional<CommNetEquipment> load(@NotNull String s) {
//                    return Optional.empty();
//                }
//            });

    private final Map<String, CommNetEquipment> netEquipmentMap = new ConcurrentHashMap<>();
    private final Map<String, CommMeter> meterNetSerial = new ConcurrentHashMap<>();
    private final Map<String, CommMeter> meterNetIndex = new ConcurrentHashMap<>();

    private final Map<String, CommValve> valveNetIndex = new ConcurrentHashMap<>();
    private final Map<String, CommValve> valveNetSerial = new ConcurrentHashMap<>();
    private final Map<String, CommPanel> panelNetIndex = new ConcurrentHashMap<>();
    private final Map<String, CommPanel> panelNetSerial = new ConcurrentHashMap<>();

    /**
     * 网络设备查找信息
     */
    public CommNetEquipment getCommNetEquipmentByNetSerial(String serial) {
        return netEquipmentMap.get(serial);
    }

    public List<CommNetEquipment> getCommNetEquipmentByNetSerial(List<String> serial) {
        return commNetEquipmentRepository.findAllBySerial(serial);
    }

    public List<CommNetEquipment> getCommNetEquipmentByType(NetEquTypeEnum typeEnum) {
        return commNetEquipmentRepository.findAll(Example.of(CommNetEquipment.builder().type(typeEnum).build()));
    }

    public CommMeter getCommMeterByNodeSerialOfHouseForNetEqu(String serial, String netIdentity) {
        return commMeterRepository.findOne(Example.of(CommMeter.builder().serial(serial).region(RegionTypeEnum.户).netEquipmentId(netIdentity).build())).orElse(null);
    }

    public CommMeter getCommMeterByNodeSerialOfBuildForNetEqu(String serial, String netIdentity) {
        return commMeterRepository.findOne(Example.of(CommMeter.builder().serial(serial).region(RegionTypeEnum.楼).netEquipmentId(netIdentity).build())).orElse(null);
    }

    public CommMeter getCommMeterByNodeSerialForNetEqu(String serial, String netIdentity) {
        CommMeter commMeter = meterNetSerial.get(netIdentity+":"+serial);
        if (commMeter == null) {
            commMeter = commMeterRepository.findOne(Example.of(CommMeter.builder().serial(serial).netEquipmentId(netIdentity).build())).orElse(null);
            if (commMeter != null) {
                meterNetSerial.put(netIdentity + ":" + serial, commMeter);
            }
        }
        return commMeter;
    }

    public void setCommMeterByNodeSerialForNetEqu(String serial, String netIdentity, CommMeter commMeter) {
        meterNetSerial.put(netIdentity+":"+serial, commMeter);
    }

    public CommMeter getCommMeterByNodeIndexForNetEqu(Integer index, String netIdentity) {
        CommMeter commMeter = meterNetIndex.get(netIdentity+":"+index);
        if (commMeter == null) {
            commMeter = commMeterRepository.findOne(Example.of(CommMeter.builder().sequence(index).netEquipmentId(netIdentity).build())).orElse(null);
            if (commMeter != null) {
                meterNetIndex.put(netIdentity + ":" + index, commMeter);
            }
        }
        return commMeter;
    }

    public void setCommMeterByNodeIndexForNetEqu(Integer index, String netIdentity, CommMeter commMeter) {
        meterNetIndex.put(netIdentity+":"+index, commMeter);
    }

    public CommValve getCommValveByNodeIndexForNetEqu(Integer index, String netIdentity) {
        CommValve commValve = valveNetIndex.get(netIdentity+":"+index);
        if (commValve == null) {
            commValve =commValveRepository.findOne(Example.of(CommValve.builder().sequence(index).netEquipmentId(netIdentity).build())).orElse(null);
            if (commValve != null) {
                valveNetIndex.put(netIdentity + ":" + index, commValve);
            }
        }
        return commValve;
    }

    public void setCommValveByNodeIndexForNetEqu(Integer index, String netIdentity, CommValve commValve) {
        valveNetIndex.put(netIdentity+":"+index, commValve);
    }


    public CommValve getCommValveByNodeSerialForNetEqu(String serial, String netIdentity) {
        CommValve commValve = valveNetSerial.get(netIdentity+":"+serial);
        if (commValve == null) {
            commValve = commValveRepository.findOne(Example.of(CommValve.builder().serial(serial).netEquipmentId(netIdentity).build())).orElse(null);
            if (commValve != null) {
                valveNetSerial.put(netIdentity + ":" + serial, commValve);
            }
        }
        return commValve;
    }

    public void setCommValveByNodeSerialForNetEqu(String serial, String netIdentity, CommValve commValve) {
        valveNetSerial.put(netIdentity+":"+serial, commValve);
    }



    public CommPanel getCommPanelByNodeIndexForNetEqu(Integer index, String netIdentity) {
        CommPanel commPanel = panelNetIndex.get(netIdentity+":"+index);
        if (commPanel == null) {
            commPanel = commPanelRepository.findOne(Example.of(CommPanel.builder().sequence(index).netEquipmentId(netIdentity).build())).orElse(null);
            if (commPanel != null) {
                panelNetIndex.put(netIdentity + ":" + index, commPanel);
            }
        }
        return commPanel;
    }

    public void setCommPanelByNodeIndexForNetEqu(Integer index, String netIdentity, CommPanel commPanel) {
        panelNetIndex.put(netIdentity+":"+index, commPanel);
    }


    public CommPanel getCommPanelByNodeSerialForNetEqu(String serial, String netIdentity) {
        CommPanel commPanel = panelNetSerial.get(netIdentity+":"+serial);
        if (commPanel == null) {
            commPanel = commPanelRepository.findOne(Example.of(CommPanel.builder().serial(serial).netEquipmentId(netIdentity).build())).orElse(null);
            if (commPanel != null) {
                panelNetSerial.put(netIdentity + ":" + serial, commPanel);
            }
        }
        return commPanel;
    }

    public void setCommPanelByNodeSerialForNetEqu(String serial, String netIdentity, CommPanel commPanel) {
        panelNetSerial.put(netIdentity+":"+serial, commPanel);
    }

    public CommValve getCommValveByNodeSerialAndCommunicationType(String serial, Integer communicationType) {
        return commValveRepository.findOne(Example.of(CommValve.builder().serial(serial).communicationType(communicationType).build())).orElse(null);
    }

    public CommValve getCommValveByNodeSerial(String serial) {
        return commValveRepository.findOne(Example.of(CommValve.builder().serial(serial).build())).orElse(null);
    }

    public List<CommValve> getCommValveByNetSerial(String netSerial) {
        return commValveRepository.findAll(Example.of(CommValve.builder().netEquipmentId(netSerial).build()));
    }
    public List<CommMeter> getCommMeterByNetSerial(String netSerial) {
        return commMeterRepository.findAll(Example.of(CommMeter.builder().netEquipmentId(netSerial).build()));
    }

    public CommTemperaturepressure getCommTemperaturepressureBySerial(String serial) {
        return commTemperaturepressureRepository.findOne(Example.of(CommTemperaturepressure.builder().serial(serial).build())).orElse(null);
    }


    public CommMeter getCommMeterBySerialAndFactory(String serial, String factory) {
        return commMeterRepository.findOne(Example.of(CommMeter.builder().serial(serial).factoryName(factory).build())).orElse(null);
    }
    public CommValve getCommValveBySerialAndFactory(String serial, String factory) {
        return commValveRepository.findOne(Example.of(CommValve.builder().serial(serial).factoryName(factory).build())).orElse(null);
    }
    public CommPanel getCommPanelBySerialAndFactory(String serial, String factory) {
        return commPanelRepository.findOne(Example.of(CommPanel.builder().serial(serial).factoryName(factory).build())).orElse(null);
    }
    public CommTemperaturepressure getCommTemperaturepressureBySerialAndFactory(String serial, String factory) {
        return commTemperaturepressureRepository.findOne(Example.of(CommTemperaturepressure.builder().serial(serial).factoryName(factory).build())).orElse(null);
    }

    private CommMeter getCommMeterBySerialAndNetDevice(String serial, String netDevice) {
        CommNetEquipment commNetEquipment = commNetEquipmentRepository.findOne(Example.of(CommNetEquipment.builder().serial(netDevice).build())).orElse(null);
        if (null == commNetEquipment) {
            return null;
        }
        return commMeterRepository.findOne(Example.of(CommMeter.builder().serial(serial).netEquipmentId(commNetEquipment.getId()).build())).orElse(null);
    }

    private CommValve getCommValveBySerialAndNetDevice(String serial, String netDevice) {
        CommNetEquipment commNetEquipment = commNetEquipmentRepository.findOne(Example.of(CommNetEquipment.builder().serial(netDevice).build())).orElse(null);
        if (null == commNetEquipment) {
            return null;
        }
        return commValveRepository.findOne(Example.of(CommValve.builder().serial(serial).netEquipmentId(commNetEquipment.getId()).build())).orElse(null);
    }

    private CommPanel getCommPanelBySerialAndNetDevice(String serial, String netDevice) {
        CommNetEquipment commNetEquipment = commNetEquipmentRepository.findOne(Example.of(CommNetEquipment.builder().serial(netDevice).build())).orElse(null);
        if (null == commNetEquipment) {
            return null;
        }
        return commPanelRepository.findOne(Example.of(CommPanel.builder().serial(serial).netEquipmentId(commNetEquipment.getId()).build())).orElse(null);
    }

    public CommMeter getCommMeter(String serial, Integer communicationType) {
        return commMeterRepository.findOne(Example.of(CommMeter.builder().serial(serial).communicationType(communicationType).build())).orElse(null);
    }

    public CommMeter getCommMeter(String serial) {
        return commMeterRepository.findOne(Example.of(CommMeter.builder().serial(serial).build())).orElse(null);
    }

    public CommMeter getCommMeter(String serial, String factory, String netDevice) {
        try {
            if (!StringUtils.isEmpty(factory)) {
                return getCommMeterBySerialAndFactory(serial, factory);
            } else if (!StringUtils.isEmpty(netDevice)) {
                return getCommMeterBySerialAndNetDevice(serial, netDevice);
            }
            return commMeterRepository.findOne(Example.of(CommMeter.builder().serial(serial).build())).orElse(null);
        } catch (Exception e) {
            log.error("getCommMeter error: {} {} {} ", serial, factory, netDevice, e);
            throw new RuntimeException(String.format("%s %s %s %s", serial, factory, netDevice, e.getMessage()));
        }

    }

    public CommValve getCommValve(String serial, String factory, String netDevice) {
        try {
            if (!StringUtils.isEmpty(factory)) {
                return getCommValveBySerialAndFactory(serial, factory);
            } else if (!StringUtils.isEmpty(netDevice)) {
                return getCommValveBySerialAndNetDevice(serial, netDevice);
            }
            return commValveRepository.findOne(Example.of(CommValve.builder().serial(serial).build())).orElse(null);
        } catch (Exception e) {
            log.error("getCommValve error: {} {} {} ", serial, factory, netDevice, e);
            throw new RuntimeException(String.format("%s %s %s %s", serial, factory, netDevice, e.getMessage()));
        }

    }

    public CommPanel getCommPanel(String serial, String factory, String netDevice) {
        try {
            if (!StringUtils.isEmpty(factory)) {
                return getCommPanelBySerialAndFactory(serial, factory);
            } else if (!StringUtils.isEmpty(netDevice)) {
                return getCommPanelBySerialAndNetDevice(serial, netDevice);
            }
            return commPanelRepository.findOne(Example.of(CommPanel.builder().serial(serial).build())).orElse(null);
        } catch (Exception e) {
            log.error("getCommPanel error: {} {} {} ", serial, factory, netDevice, e);
            throw new RuntimeException(String.format("%s %s %s %s", serial, factory, netDevice, e.getMessage()));
        }
    }

    public CommTemperaturepressure getCommTemperaturepressure(String serial, String factory, String netDevice) {
        try {
            if (!StringUtils.isEmpty(factory)) {
                return getCommTemperaturepressureBySerialAndFactory(serial, factory);
            }
            return getCommTemperaturepressureBySerial(serial);
        } catch (Exception e) {
            log.error("getCommTemperaturepressure error: {} {} {} ", serial, factory, netDevice, e);
            throw new RuntimeException(String.format("%s %s %s %s", serial, factory, netDevice, e.getMessage()));
        }

    }

    public CommValve getCommValveByNodeSerialOfHouseForNetEqu(String serial, String netIdentity) {
        return commValveRepository.findOne(Example.of(CommValve.builder().serial(serial).region(RegionTypeEnum.户).netEquipmentId(netIdentity).build())).orElse(null);
    }

    public CommValve getCommValveByNodeSerialOfBuildForNetEqu(String serial, String netIdentity) {
        return commValveRepository.findOne(Example.of(CommValve.builder().serial(serial).region(RegionTypeEnum.楼).netEquipmentId(netIdentity).build())).orElse(null);
    }

    public CommPanel getCommPanel(String serial, Integer communicationType) {
        return commPanelRepository.findOne(Example.of(CommPanel.builder().serial(serial).communicationType(communicationType).build())).orElse(null);
    }

    public CommPanel getCommPanelByNodeSerial(String serial) {//NB暂使用这个,后期需标准类型
        return commPanelRepository.findOne(Example.of(CommPanel.builder().serial(serial).build())).orElse(null);
    }


    public CommValve getCommValveByNodeIdentity(String identity) {
        return commValveRepository.findById(identity).orElse(null);
    }

    public List<CommPanel> getListCommPanelByNodeModel(String model) {
        return commPanelRepository.findAll(Example.of(CommPanel.builder().model(model).build()));
    }
    public List<CommTemperaturepressure> getListCommTemperaturepressureByNodeModel() {
        return commTemperaturepressureRepository.findAll();
    }

    public CommTemperaturepressure getCommTemperaturepressure(String serial) {
        return commTemperaturepressureRepository.findOne(Example.of(CommTemperaturepressure.builder().serial(serial).build())).orElse(null);
    }


    /**
     * 东营NB专用
     *
     * @param serial
     * @param factoryName
     * @return
     */
    public CommValve getCommValveOfDongYing(String serial, String factoryName) {
        return commValveRepository.findOne(Example.of(CommValve.builder().serial(serial).communicationType(3).factoryName(factoryName).build())).orElse(null);
    }

    public String getCommNodeIdByIndexAndNetId(String netId, Integer index) {
        CommMeter commMeter = commMeterRepository.findOne(Example.of(CommMeter.builder()
                .sequence(index).netEquipmentId(netId).build())).orElse(null);
        if (commMeter != null) {
            return commMeter.getId();
        }
        CommValve commValve = commValveRepository.findOne(Example.of(CommValve.builder()
                .sequence(index).netEquipmentId(netId).build())).orElse(null);
        if (commValve != null) {
            return commValve.getId();
        }
        CommPanel commPanel = commPanelRepository.findOne(Example.of(CommPanel.builder()
                .sequence(index).netEquipmentId(netId).build())).orElse(null);
        if (commPanel != null) {
            return commPanel.getId();
        }
        log.error("getCommNodeIdByIndexAndNetId未找到设备netId:{},index:{}", netId, index);
        return null;
    }


    /**
     * -------------------------------------nb
     */
    public CommNbcmd getCommNBCmdById(String id) {
        return commNbcmdRepository.findById(id).orElse(null);
    }

}
